from .attributes import *

import gdal

from gdalconst import *


class GeoData(Object):
    filename = Attribute()
    
    dataset = Attribute(initiable = False)
    
    def setup(self):
        gdal.AllRegister()
        
        self.dataset = gdal.Open(self.filename, GA_ReadOnly)
    
    @property
    def width(self):
        return self.dataset.RasterXSize
    
    @property
    def height(self):
        return self.dataset.RasterYSize
    
    @property
    def origin(self):
        geo = self.dataset.GetGeoTransform()
        
        return (geo[0], geo[3])
    
    @property
    def pixel_size(self):
        geo = self.dataset.GetGeoTransform()
        
        return (geo[1], geo[5])
    
    def x_index_of(self, coord):
        return int((coord - self.origin[0]) / self.pixel_size[0])
    
    def y_index_of(self, coord):
        return int((coord - self.origin[1]) / self.pixel_size[1])
    
    def index_of(self, x, y):
        return (self.x_index_of(x), self.y_index_of(y))
    
    def x_values_between(self, x1, x2):
        return self.x_index_of(x2) - self.x_index_of(x1) + 1
    
    def y_values_between(self, y1, y2):
        return self.x_index_of(y2) - self.x_index_of(y1) + 1
    
    def at_index(self, x, y):
        return self.dataset.GetRasterBand(1).ReadAsArray(x, y, 1, 1)[0, 0]
    
    def value(self, x, y):
        return self.at_index(*self.index_of(x, y))
    
    def area(self, center, size):
        return GeoArea(self, center, size)


class GeoArea(Object):
    center = Attribute()
    size   = Attribute()
    
    layer  = Attribute(initiable = False)
    
    def setup(self):
        self.layer = GeoData('/home/mn/Temp/g10g.bil')
    
    def x_coordinate_at(self, x):
        return self.center[0] + (x - 0.5) * self.size[0]
    
    def y_coordinate_at(self, y):
        return self.center[1] - (y - 0.5) * self.size[1]
    
    def coordinates_at(self, x, y):
        return (self.x_coordinate_at(x), self.y_coordinate_at(y))
    
    def height(self, x, y):
        return self.layer.value(*self.coordinates_at(x, y))
